package com.sky.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.result.PageResult;
import com.sky.service.DishFlavorService;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author FangKun
 * @create 2024-04-08-11:36
 */
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private DishMapper dishMapper;

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private DishFlavorMapper dishFlavorMapper;

    @Autowired
    private SetmealDishMapper setmealDishMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public PageResult queryPage(DishPageQueryDTO dishPageQueryDTO) {
        PageHelper.startPage(dishPageQueryDTO.getPage(),dishPageQueryDTO.getPageSize());
        Page<DishVO> page = dishMapper.queryPage(dishPageQueryDTO);
        long total = page.getTotal();
        List<DishVO> records = page.getResult();
        return new PageResult(total,records);
    }

    @Override
    public void updateDishStatus(Integer status, Long id) {
        Dish dish = new Dish();
        dish.setStatus(status);
        dish.setId(id);
        dish.setUpdateTime(LocalDateTime.now());
        dish.setUpdateUser(BaseContext.getCurrentId());
        baseMapper.updateById(dish);

        cleanCache("dish_*");
    }

    @Override
    @Transactional
    public void addDish(DishDTO dishDTO) {

        // 菜品信息
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish);
        dish.setStatus(StatusConstant.DISABLE);
        dish.setCreateUser(BaseContext.getCurrentId());
        dish.setCreateTime(LocalDateTime.now());
        dish.setUpdateUser(BaseContext.getCurrentId());
        dish.setUpdateTime(LocalDateTime.now());
        baseMapper.insert(dish);

        // 风味信息
        Long dishId = dish.getId();
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if (flavors != null && flavors.size() > 0){
            flavors.forEach(flavor -> {
                flavor.setDishId(dishId);
            });
            dishFlavorMapper.insertBatch(flavors);
        }

        String redisKey = "dish_" + dishDTO.getCategoryId();
        cleanCache(redisKey);

    }

    @Override
    public DishVO selectDishById(Long id) {
        DishVO dishVO = new DishVO();

        Dish dish = dishMapper.selectById(id);
        BeanUtils.copyProperties(dish,dishVO);

        List<DishFlavor> dishFlavors = dishFlavorService.selectFlavorList(dish.getId());

        dishVO.setFlavors(dishFlavors);

        return dishVO;
    }

    @Override
    @Transactional
    public void updateDish(DishDTO dishDTO) {

        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish);
        dish.setUpdateTime(LocalDateTime.now());
        dish.setUpdateUser(BaseContext.getCurrentId());
        baseMapper.updateById(dish);

        // 修改风味:先将原本的对应风味全部删掉，然后添加新的记录
        Long dishId = dishDTO.getId();
        LambdaQueryWrapper<DishFlavor> flavorWrapper = new LambdaQueryWrapper<>();
        flavorWrapper.eq(DishFlavor::getDishId,dishId);
        dishFlavorMapper.delete(flavorWrapper);

        List<DishFlavor> flavors = dishDTO.getFlavors();
        if (flavors != null && flavors.size() > 0) {
            flavors.forEach(flavor -> {
                flavor.setDishId(dishId);
            });
            dishFlavorMapper.insertBatch(flavors);
        }

        cleanCache("dish_*");
    }

    private void cleanCache(String pattern) {
        Set keys = redisTemplate.keys(pattern);
        redisTemplate.delete(keys);
    }

    @Override
    @Transactional
    public void deleteDish(List<Long> ids) {
        // 是否起售中
        LambdaQueryWrapper<Dish> dishWrapper = new LambdaQueryWrapper<>();
        dishWrapper.in(Dish::getId,ids).eq(Dish::getStatus,StatusConstant.ENABLE);
        Integer count = baseMapper.selectCount(dishWrapper);
        if (count > 0){
            throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
        }

        // 是否被套餐关联
        LambdaQueryWrapper<SetmealDish> setmealDishWrapper = new LambdaQueryWrapper<>();
        setmealDishWrapper.in(SetmealDish::getDishId,ids);
        Integer setmealcount = setmealDishMapper.selectCount(setmealDishWrapper);
        if (setmealcount > 0){
            throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
        }

        // 删除菜品
        baseMapper.deleteBatchIds(ids);

        // 删除对应口味
        LambdaQueryWrapper<DishFlavor> flavorWrapper = new LambdaQueryWrapper<>();
        flavorWrapper.in(DishFlavor::getDishId,ids);
        dishFlavorMapper.delete(flavorWrapper);

        cleanCache("dish_*");

    }

    @Override
    public List<DishVO> listWithFlavor(Long categoryId) {

        String redisKey =  "dish_" + categoryId.toString();
        List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(redisKey);

        if (list != null && list.size() > 0){
            return list;
        } else {
            LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
            dishLambdaQueryWrapper.eq(Dish::getCategoryId,categoryId);
            dishLambdaQueryWrapper.eq(Dish::getStatus,StatusConstant.ENABLE);
            List<Dish> dishList = baseMapper.selectList(dishLambdaQueryWrapper);

            list = new ArrayList<>();

            for (Dish dish : dishList) {
                DishVO dishVO = new DishVO();
                BeanUtils.copyProperties(dish,dishVO);

                List<DishFlavor> flavorList = dishFlavorService.selectFlavorList(dish.getId());
                dishVO.setFlavors(flavorList);
                list.add(dishVO);
            }

            redisTemplate.opsForValue().set(redisKey,list);
        }
        return list;
    }

    @Override
    public List<Dish> selectDishByCategoryId(Long categoryId) {

        LambdaQueryWrapper<Dish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Dish::getCategoryId,categoryId);
        List<Dish> dishList = baseMapper.selectList(queryWrapper);
        return dishList;
    }
}


















